package AircraftDesignKg.server;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.neo4j.driver.*;
import org.neo4j.driver.summary.SummaryCounters;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.Map;

/**
 * Neo4j命令服务 - 负责将AI生成的JSON响应转换为Neo4j Cypher指令并执行
 *
 * 主要功能：
 * 1. 解析AI生成的JSON响应
 * 2. 生成Cypher创建语句
 * 3. 执行Cypher指令操作Neo4j数据库
 * 4. 处理异常并记录日志
 *
 * 设计说明：
 * - 使用Jackson库解析JSON
 * - 使用Neo4j官方Java Driver执行Cypher
 * - 幂等性设计：使用MERGE确保重复操作不会产生重复数据
 * - 支持动态节点标签和关系类型
 * - 自动处理属性值类型（字符串需特殊转义）
 */
@Service
public class Neo4jCommandService extends AbstractService<String, String> implements InitializingBean {

    private static final Logger log = LogManager.getLogger(Neo4jCommandService.class);

    // Neo4j连接配置（从application.yml注入）
    @Value("${spring.neo4j.url}")
    private String neo4jUri;

    @Value("${spring.neo4j.authentication.username}")
    private String username;

    @Value("${spring.neo4j.authentication.password}")
    private String password;

    private Driver driver; // Neo4j驱动实例
    private final ObjectMapper objectMapper = new ObjectMapper(); // JSON解析器

    /**
     * 宽松 JSON 转化
     */
    @PostConstruct
    private void init() {
        this.objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        this.objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        this.objectMapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
    }

    /**
     * Spring Bean初始化回调方法
     * 初始化Neo4j驱动连接
     */
    @Override
    public void afterPropertiesSet() {
        // 创建Neo4j驱动实例
        this.driver = GraphDatabase.driver(neo4jUri, AuthTokens.basic(username, password));
        log.info("Neo4j驱动初始化成功, URI: {}", neo4jUri);
    }

    /**
     * 服务主入口 - 处理AI生成的JSON响应
     *
     * @param jsonResponse AI生成的JSON格式响应
     * @return 操作结果描述
     * @throws Exception 处理过程中的任何异常
     */
    @Override
    public String doProcess(String jsonResponse) throws Exception {
        try {
            log.debug("开始处理AI生成的JSON响应");

            // 步骤1: 生成Cypher命令
            String cypherCommand = generateCommand(jsonResponse);
            log.info("生成的Cypher命令: {}", cypherCommand);

            // 步骤2: 执行Cypher命令
            executeCommand(cypherCommand);

            return "Neo4j操作执行成功";
        } catch (Exception e) {
            log.error("Neo4j命令处理失败", e);
            throw new Exception("Neo4j操作执行失败: " + e.getMessage(), e);
        }
    }

    public String generateCommand(String jsonResponse) throws Exception {
        try {
            JsonNode rootNode = objectMapper.readTree(jsonResponse);
            // 提取并预处理content字段
            String graphContent = extractContent(rootNode);
            graphContent = preprocessJsonString(graphContent);
            // 二次解析
            JsonNode graphNode = objectMapper.readTree(graphContent);
            // 验证核心结构
            validateGraphStructure(graphNode);

            // 生成Cypher命令
            StringBuilder cypherBuilder = new StringBuilder();

            // 处理节点
            for (JsonNode node : graphNode.get("nodes")) {
                processNode(cypherBuilder, node);
            }

            // 处理关系
            for (JsonNode rel : graphNode.get("relationships")) {
                processRelationship(cypherBuilder, rel);
            }

            return cypherBuilder.toString();

        } catch (Exception e) {
            log.error("JSON转Cypher失败: {}", jsonResponse, e);
            throw new Exception("图数据处理失败: " + e.getMessage(), e);
        }
    }

    // 提取content内容
    private String extractContent(JsonNode rootNode) throws Exception {
        if (!rootNode.has("choices")) {
            throw new Exception("API响应缺少choices字段");
        }
        JsonNode choices = rootNode.get("choices");
        if (choices.isEmpty()) {
            throw new Exception("choices数组为空");
        }
        JsonNode message = choices.get(0).get("message");
        if (message == null || !message.has("content")) {
            throw new Exception("message对象缺少content字段");
        }
        return message.get("content").asText();
    }

    // JSON字符串预处理
    private String preprocessJsonString(String json) {
        return json.replace("\\\"", "\"")
                .replace("\\\\", "\\")
                .trim();
    }

    // 验证图数据结构
    private void validateGraphStructure(JsonNode graphNode) throws Exception {
        if (!graphNode.has("nodes")) {
            throw new Exception("图数据缺少nodes字段");
        }

        if (!graphNode.has("relationships")) {
            throw new Exception("图数据缺少relationships字段");
        }
    }

    /**
     * 处理单个节点，生成节点创建Cypher
     *
     * @param cypherBuilder 用于构建Cypher语句的StringBuilder
     * @param node 节点JSON对象
     */
    private void processNode(StringBuilder cypherBuilder, JsonNode node) {
        // 提取节点属性
        String id = node.path("id").asText();
        JsonNode labels = node.path("labels");
        JsonNode properties = node.path("properties");

        // MERGE确保幂等性 - 基于id属性判断是否存在
        cypherBuilder.append("MERGE (n").append(id).append(" {id: '").append(id).append("'})\n");

        // 设置节点属性
        cypherBuilder.append("SET n").append(id).append(" += ");
        appendProperties(cypherBuilder, properties);

        // 设置节点标签（支持多个标签）
        if (labels.isArray() && labels.size() > 0) {
            cypherBuilder.append("\nSET n").append(id).append(" :");
            for (int i = 0; i < labels.size(); i++) {
                if (i > 0) cypherBuilder.append(":");
                cypherBuilder.append(labels.get(i).asText());
            }
        }
        cypherBuilder.append(";\n"); // 结束语句
    }

    /**
     * 处理单个关系，生成关系创建Cypher
     *
     * @param cypherBuilder 用于构建Cypher语句的StringBuilder
     * @param rel 关系JSON对象
     */
    private void processRelationship(StringBuilder cypherBuilder, JsonNode rel) {
        // 提取关系属性
        String type = rel.path("type").asText();
        String from = rel.path("from").asText();
        String to = rel.path("to").asText();
        JsonNode properties = rel.path("properties");

        // 匹配起始节点和结束节点
        cypherBuilder.append("MATCH (a {id: '").append(from).append("'}), (b {id: '").append(to).append("'})\n");

        // 创建关系（MERGE确保幂等性）
        cypherBuilder.append("MERGE (a)-[r:").append(type).append("]->(b)\n");

        // 设置关系属性
        cypherBuilder.append("SET r += ");
        appendProperties(cypherBuilder, properties);
        cypherBuilder.append(";\n"); // 结束语句
    }

    /**
     * 将JSON属性节点转换为Cypher属性格式
     *
     * @param builder 用于构建Cypher语句的StringBuilder
     * @param properties 属性JSON对象
     */
    private void appendProperties(StringBuilder builder, JsonNode properties) {
        builder.append("{ ");
        Iterator<Map.Entry<String, JsonNode>> fields = properties.fields();

        // 遍历所有属性键值对
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> field = fields.next();
            String key = field.getKey();
            JsonNode value = field.getValue();

            builder.append(key).append(": ");

            // 处理不同属性值类型
            if (value.isTextual()) {
                // 字符串类型：添加引号并转义单引号
                builder.append("'").append(value.asText().replace("'", "\\'")).append("'");
            } else {
                // 其他类型（数字、布尔等）：直接使用
                builder.append(value.toString());
            }

            // 添加逗号分隔（最后一个属性不加）
            if (fields.hasNext()) builder.append(", ");
        }
        builder.append(" }");
    }

    /**
     * 执行Cypher命令
     *
     * @param command 要执行的Cypher语句
     * @throws RuntimeException 数据库操作失败时抛出
     */
    public void executeCommand(String command) {
        try (Session session = driver.session()) {
            // 拆分成多条语句
            String[] statements = command.split(";");

            for (String stmt : statements) {
                String trimmedStmt = stmt.trim();
                if (!trimmedStmt.isEmpty()) {
                    log.debug("执行 Cypher: {}", trimmedStmt);
                    session.run(trimmedStmt);
                }
            }
            log.info("Cypher 执行完成");

        } catch (Exception e) {
            log.error("Cypher执行失败: {}", command, e);
            throw new RuntimeException("数据库操作失败: " + e.getMessage(), e);
        }
    }


    /**
     * 关闭Neo4j驱动连接
     * 通常在应用关闭时调用
     */
    public void shutdown() {
        if (driver != null) {
            driver.close();
            log.info("Neo4j驱动已关闭");
        }
    }
}